package com.heicoder.poster.image;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.heicoder.poster.entity.HeadImage;
import com.heicoder.poster.entity.NickName;
import com.heicoder.poster.entity.QrCode;
import com.heicoder.poster.util.Base64Utils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Hashtable;

/**
 * @author wuyunbin
 */
public class PosterBuilder {
    private BufferedImage templateImage;
    private Graphics2D templateG2D;
    private int templateWidth;
    private int templateHeight;

    public PosterBuilder(String imageUrl) {
        try {
            URL url = new URL(imageUrl);
            templateImage = ImageIO.read(url);
            templateG2D = templateImage.createGraphics();
            templateWidth = templateImage.getWidth();
            templateHeight = templateImage.getHeight();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public PosterBuilder addQrCode(QrCode qrCode) {
        BufferedImage qrCodeImage = createQrCodeImage(qrCode.getText());
        int x = (new Double((templateWidth * 0.01) * qrCode.getxPercent()).intValue());
        int y = (new Double((templateHeight * 0.01) * qrCode.getyPercent()).intValue());
        int width = (new Double((templateWidth * 0.01) * qrCode.getWidth()).intValue());
        int height = (new Double((templateWidth * 0.01) * qrCode.getHeight()).intValue());
        templateG2D.drawImage(qrCodeImage, x, y, width, height, null);
        return this;
    }

    public PosterBuilder addHeadImage(HeadImage headImage) {
        BufferedImage headBufferedImage;
        try {
            URL url = new URL(headImage.getHeadImageUrl());
            InputStream is = url.openConnection().getInputStream();
            headBufferedImage = ImageIO.read(is);
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        int x = (new Double((templateWidth * 0.01) * headImage.getxPercent()).intValue());
        int y = (new Double((templateHeight * 0.01) * headImage.getyPercent()).intValue());
        int width = (new Double((templateWidth * 0.01) * headImage.getWidth()).intValue());
        int height = (new Double((templateWidth * 0.01) * headImage.getHeight()).intValue());
        Ellipse2D.Double shape = new Ellipse2D.Double(x, y, width, height);
        templateG2D.setClip(shape);
        templateG2D.drawImage(headBufferedImage, x, y, width, height, null);
        return this;
    }


    public PosterBuilder addNickname(NickName nickName) {
        int x = (new Double((templateWidth * 0.01) * nickName.getxPercent()).intValue());
        int y = (new Double((templateHeight * 0.01) * nickName.getyPercent()).intValue());
        float fontSize = (new Double((templateWidth * 0.01) * nickName.getFontSize()).intValue());
        templateG2D.setFont(templateG2D.getFont().deriveFont(fontSize));
        templateG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        templateG2D.setColor(Color.BLACK);
        templateG2D.drawString(nickName.getNickname(), x, y);
        return this;
    }

    public void build() {
        templateG2D.dispose();
        templateImage.flush();
        try {
            String now = System.currentTimeMillis() + "";
            ImageIO.write(templateImage, "jpg", new File("poster" + now + ".jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.gc();
    }

    public String getBase64() {
        templateG2D.dispose();
        templateImage.flush();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            ImageIO.write(templateImage, "jpg", outputStream);
            return "data:image/jpg;base64," + Base64Utils.encodeToString(outputStream.toByteArray()).toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    private BufferedImage createQrCodeImage(String qrcodeText) {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
        // 指定纠错等级,纠错级别（L 7%、M 15%、Q 25%、H 30%）
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 内容所使用字符集编码
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        //设置二维码边的空度，非负数
        hints.put(EncodeHintType.MARGIN, 1);
        try {
	       	/*
	       	qrcodeText,//要编码的内容
			           //编码类型，目前zxing支持：Aztec 2D,CODABAR 1D format,Code 39 1D,Code 93 1D ,Code 128 1D,
			           //Data Matrix 2D , EAN-8 1D,EAN-13 1D,ITF (Interleaved Two of Five) 1D,
			           //MaxiCode 2D barcode,PDF417,QR Code 2D,RSS 14,RSS EXPANDED,UPC-A 1D,UPC-E 1D,UPC/EAN extension,UPC_EAN_EXTENSION
			           BarcodeFormat.QR_CODE,
			           300, //二维码宽度
			           300, //二维码高度
			           hints);//生成条形码时的一些配置,此项可选
	       	 */
            BitMatrix bitMatrix = new MultiFormatWriter().encode(qrcodeText, BarcodeFormat.QR_CODE, 300, 300, hints);
            return MatrixToImageWriter.toBufferedImage(bitMatrix);
        } catch (WriterException e) {
            e.printStackTrace();
        }
        return null;
    }

}
